package kernel;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;

public class Volume {

	private ArrayList<double[]> points;
	private ArrayList<int[]> triangleStrips;
	private double[] boundingMin;
	private double[] boundingMax;
	private double volumeBoundngBoxWidth;
	private double volumeBoundingBoxHeight;
	private double volumeBoundingBoxDepth;
	private double[] center;
	private boolean withLog;
	private Color color;
	private String name;
	private double volumeMm;
	
	public Volume()
	{
		boundingMin = new double[]{Double.MAX_VALUE, Double.MAX_VALUE,Double.MAX_VALUE};
		boundingMax = new double[]{Double.MIN_VALUE, Double.MIN_VALUE,Double.MIN_VALUE};
		center = new double[3];
		points = new ArrayList<double[]>();
		triangleStrips = new ArrayList<int[]>();
		withLog = true;
		color = Color.RED;
	}
	
	public void setVolume(double nVolumeMm)
	{
		volumeMm=nVolumeMm;
	}
	
	public double getVolume()
	{
		return volumeMm;
	}
	
	public void readFile(File file, Color color) throws Exception
	{
		this.color = color;
		name = file.getAbsolutePath();
		System.out.println("Start Loading: " + file.getAbsolutePath());
		BufferedReader buffReader = new BufferedReader(new FileReader(file));
		String line = "";

		boolean readingpoints = false;
		boolean readingTriangleStrips = false;
		ArrayList<Double> vertices = new ArrayList<Double>();
		int lineNumber = 1;
		while ((line =buffReader.readLine())!= null)
		{
			if(line.contains("POINTS"))
			{
//				System.out.println("File info -> " + line);
				readingpoints = true;
				continue;
			}
			if(line.contains("TRIANGLE_STRIPS"))
			{
//				System.out.println("File info -> " + line);
				readingpoints = false;
				readingTriangleStrips = true;
				if(withLog)
				{
					System.out.println("Vertices: " + vertices.size());
				}
				for(int i = 0; i < vertices.size(); i+=3)
				{
					try {
						double x = vertices.get(i);
						double y = vertices.get(i + 1);
						double z = vertices.get(i + 2);

						if(x < boundingMin[0])
						{
							boundingMin[0] = x;
						}
						if(x > boundingMax[0])
						{
							boundingMax[0] = x;
						}
						if(y < boundingMin[1])
						{
							boundingMin[1] = y;
						}
						if(y > boundingMax[1])
						{
							boundingMax[1] = y;
						}
						if(z < boundingMin[2])
						{
							boundingMin[2] = z;
						}
						if(z > boundingMax[2])
						{
							boundingMax[2] = z;
						}

						points.add(new double[]{
								x,
								y,
								z
						});

					} catch (Exception e) {
						System.err.println("Vertices " + i + " could not be read");
					}
				}
				continue;
			}
			if(line.contains("POINT_DATA"))
			{

				break;
			}

			if(readingpoints)
			{
				String[] parser = line.split("\\s");
				if(parser.length % 3 != 0)
				{
					System.err.println("Error in parsing: " + lineNumber + " --- " + parser.length);
				}
				for(int i = 0; i < parser.length; i++)
				{
					try {
						vertices.add(Double.parseDouble(parser[i]));
					} catch (Exception e) {
						System.err.println("Error line " + lineNumber + " parser size: " + parser.length);
					}
				}
			}

			if(readingTriangleStrips)
			{ 
				String[] parser = line.split(" ");
				if(parser.length > 3)
				{
					int numberOfVertices = Integer.parseInt(parser[0]);
					int[] triangleStrip = new int[numberOfVertices];
					for(int i = 0; i < numberOfVertices; i++)
					{
						int vertex = Integer.parseInt(parser[i + 1]);
						triangleStrip[i] = vertex;
					}
					triangleStrips.add(triangleStrip);
				}
				else
				{
					System.err.println("Line " + lineNumber + " not read");
				}
			}
			lineNumber++;
		}

		buffReader.close();
		
		if(triangleStrips.isEmpty())
		{
			throw new Exception("file " + file.getAbsolutePath() + " is not a volume");
		}
		
		buffReader.close();
		if(withLog)
		{
			System.out.println("Points: " + points.size());
			System.out.println("Triangle Strips:  " + triangleStrips.size());
			System.out.println("Bounds:\n\tXmin,Xmax: (" +boundingMin[0] + ", " + boundingMax[0] + ")");
			System.out.println("\tYmin,Ymax: (" + boundingMin[1] + ", " + boundingMax[1] + ")");
			System.out.println("\tZmin,Zmax: (" + boundingMin[2] + ", " + boundingMax[2] + ")");
		}


		volumeBoundngBoxWidth = (boundingMax[0] - boundingMin[0]);
		volumeBoundingBoxHeight = (boundingMax[1] - boundingMin[1]);
		volumeBoundingBoxDepth = (boundingMax[2] - boundingMin[2]);

		center[0] =  boundingMin[0] + volumeBoundngBoxWidth/2;
		center[1] =  boundingMin[1] + volumeBoundingBoxHeight/2;
		center[2] =  boundingMin[2] + volumeBoundingBoxDepth/2;

		if(withLog)
			System.out.println("Width = " + volumeBoundngBoxWidth + " Height: " + volumeBoundingBoxHeight + " Depth = " + volumeBoundingBoxDepth + " Center: " + center[0] + ", " + center[1] + ", " + center[2]);

		System.out.println("End Loading  : " + file.getAbsolutePath());
	}

	public void setColor(Color color)
	{
		this.color = color; 
	}
	
	public ArrayList<double[]> getPoints() {
		return points;
	}

	public ArrayList<int[]> getTriangleStrips() {
		return triangleStrips;
	}

	public double[] getBoundingMin() {
		return boundingMin;
	}

	public double[] getBoundingMax() {
		return boundingMax;
	}

	public double getVolumeBoundngBoxWidth() {
		return volumeBoundngBoxWidth;
	}

	public double getVolumeBoundingBoxHeight() {
		return volumeBoundingBoxHeight;
	}

	public double getVolumeBoundingBoxDepth() {
		return volumeBoundingBoxDepth;
	}

	public double[] getCenter() {
		return center;
	}
	
	public Color getColor()
	{
		return color;
	}
	
	public String getName()
	{
		return name;
	}
	
}
